/*
 * Copyright (c) 2013-2018 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Driver_USART.h"
#include "RTE_Device.h"
#include "GPIO_STM32F10x.h"
#include "wingbot_usart.h"
#include "wingbot_queue.h"
#include "wingbot_tick.h"
#include "wingbot_timer.h"
#include "RS485.h"

extern uint8_t usart3_rx_buffer[128];
extern Queue_T usart3_rx_queue;
void wing_usart3_irq_handler(void);

#define USART3_RX_INTERVAL 6U    //两帧之间的时间间隔6ms

#if !(defined null_ptr)
#define null_ptr (void*)0
#endif

USART_INFO USART3_Info = {
    .port        = USART3,
    .irq_handler = wing_usart3_irq_handler,
    .baudrate    = 9600,
    .parity      = USART_Parity_No,
    .stopbits    = USART_StopBits_1,
    .trans_info  = {
        .rx_que         = &usart3_rx_queue,
        .rx_tick        = 0U,
        .rx_cnt         = 0U,
        .rx_state       = TRANS_IDLE,
        .rx_dataReady   = false
    }
};

/**
* @brief 中断处理程序
*/
void wing_usart3_irq_handler(void)
{
    u8 data = 0;
    if(USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == SET)//接收数据寄存器非空标志位
    {
        data = USART_ReceiveData(USART3);
        queue_push(&usart3_rx_queue, data);
        USART3_Info.trans_info.rx_tick = wing_get_tick(TIM2);
        USART3_Info.trans_info.rx_state = TRANS_WAITING;
    }
}

bool usart3_data_ready(void)
{
    /* 超过usart3_RX_INTERVAL时间没有收到消息说明上次发送已经结束 */
    uint32_t time = USART3_Info.trans_info.rx_tick;
    if((uint32_t)(wing_get_tick(TIM2) - time) > USART3_RX_INTERVAL)
    {
        /* 特殊情况当 wing_get_tick(TIM2) = 1, time = 5999999, 说明计时器已经溢出归0
        但是 (uint32_t)(1-5999999) > USART3_RX_INTERVAL 仍然为真 */
        USART3_Info.trans_info.rx_state = TRANS_FINISH;
        return true;
    }
    else
        return false;
}

int32_t ARM_USART3_Initialize(ARM_USART_SignalEvent_t cb_event)
{
    GPIO_PortClock(RTE_USART3_TX_PORT, true);
    GPIO_PortClock(RTE_USART3_RX_PORT, true);
    GPIO_PinConfigure(RTE_USART3_TX_PORT, RTE_USART3_TX_BIT, GPIO_AF_PUSHPULL, GPIO_MODE_OUT50MHZ);
    GPIO_PinConfigure(RTE_USART3_RX_PORT, RTE_USART3_RX_BIT, GPIO_IN_PULL_UP, GPIO_MODE_INPUT);
    wing_usart_init(USART3, USART3_Info.baudrate, USART3_Info.parity, USART3_Info.stopbits);
    wing_usart_nvic_init(USART3);
    return ARM_DRIVER_OK;
}

int32_t ARM_USART3_Uninitialize(void)
{
    return ARM_DRIVER_OK;
}

int32_t ARM_USART3_PowerControl(ARM_POWER_STATE state)
{
    switch (state)
    {
    case ARM_POWER_OFF:
        break;

    case ARM_POWER_LOW:
        break;

    case ARM_POWER_FULL:
        break;

    default:
        return ARM_DRIVER_ERROR_UNSUPPORTED;
    }
    return ARM_DRIVER_OK;
}

int32_t ARM_USART3_Send(const void *data, uint32_t num)
{
    RS485_SetMode(USART3, RS485Wr);
    wing_usart_send_bytes(USART3, (uint8_t *)data, num);
    RS485_SetMode(USART3, RS485Rd);
    return ARM_DRIVER_OK;
}

int32_t ARM_USART3_Receive(void *data, uint32_t num)
{
    queue_read(USART3_Info.trans_info.rx_que, (uint8_t *)data, num);
    USART3_Info.trans_info.rx_dataReady = false;  //读完后清空数据标志，即使缓存里面还有数据
    return ARM_DRIVER_OK;
}

// End USART Interface

ARM_DRIVER_USART Driver_USART3 = {
    .GetVersion = null_ptr,
    .GetCapabilities = null_ptr,
    ARM_USART3_Initialize,
    ARM_USART3_Uninitialize,
    ARM_USART3_PowerControl,
    ARM_USART3_Send,
    ARM_USART3_Receive,
    .Transfer = null_ptr,
    .GetTxCount = null_ptr,
    .GetRxCount = null_ptr,
    .Control = null_ptr,
    .GetStatus = null_ptr,
    .SetModemControl = null_ptr,
    .GetModemStatus = null_ptr
};
